package com.dwy.decodemjpeg

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.util.Log
import android.widget.ImageView
import android.widget.Toast
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.net.InetSocketAddress
import java.net.Socket
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

object MjpegDecoderManager {

    private lateinit var mjpegMediaCodecPlayer: MjpegMediaCodecPlayer
    private var mCameraSaocket: Socket? = null
    private var mVideoCSaocket: Socket? = null
    private val TAG = "MjpegDecoderManager"
    private var firstFrameComing = false
    private var rotationDegree: Float = 0f

    fun connectCamera(): Boolean {
        try {
            if (TestConfig.ifServerSendData) {
                mVideoCSaocket = Socket()
                mVideoCSaocket?.connect(InetSocketAddress("172.18.14.156" ,1989), 6000)
                if (mVideoCSaocket?.isConnected == true) {
                    Log.d(TAG, "openCamera: mVideoCSaocket connect success")
                    return true
                } else {
                    Log.d(TAG, "openCamera: mVideoCSaocket connect fail")
                    return false
                }
            } else {
                mCameraSaocket = Socket()
                mCameraSaocket?.connect(InetSocketAddress("192.168.10.1", 7100), 6000)
                return if (mCameraSaocket?.isConnected == true) {
                    Log.d(TAG, "openCamera: mCameraSaocket connect success")
                    true
                } else {
                    Log.d(TAG, "openCamera: mCameraSaocket connect fail")
                    false
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            return false
        }
    }

    fun configVideoFormat(): Boolean {
        return sendMsg(ObjectUtil.parseHexStringToBytes("D5F0 0100 AE727272 0300 1600 44 000000 01000000 00000000 0C00 646F6F7262656C6C2D746370"))
    }

    fun openCamera(pixelType: Int = 0): Boolean {
        return sendMsg(ObjectUtil.parseHexStringToBytes(when (pixelType) {
            0 -> {
                //1280*720
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 e4 000000 07000000 f6fd0000 0800 0005 d002 0000 0200"))
            }
            1 -> {
                //1024*720
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 37 000000 07000000 f6fd0000 0800 0004 d002 0000 0200"))
            }
            2 -> {
                //800*480
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 e9 000000 07000000 f6fd0000 0800 2003 e001 0000 0200"))
            }
            3 -> {
                //640*480
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 63 000000 07000000 f6fd0000 0800 8002 e001 0000 0200"))
            }
            4 -> {
                //480*320
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 5a 000000 07000000 f6fd0000 0800 e001 4001 0000 0200"))
            }
            else -> ""
        }))
    }

    fun startVideoPlay(ivPic: ImageView, onSuccess: () -> Unit, onFail: ((throwable: Throwable) -> Unit)? = null) {
        try {
            //var videoSocketIsNew = false
            val videoSocketAddress = if (TestConfig.ifServerSendData) {
                InetSocketAddress("172.18.14.156" ,1989)
            } else {
                InetSocketAddress("192.168.10.1", 7150)
            }
            MjpegMediaCodecPlayer.handleLog("VideoCSaocket.isClosed:${mVideoCSaocket?.isClosed},mVideoCSaocket.isConnected:${mVideoCSaocket?.isConnected}")
            try {
                mVideoCSaocket = Socket()
                mVideoCSaocket?.connect(videoSocketAddress, 6000)
            } catch (e: Exception) {
                e.printStackTrace()
                onFail?.invoke(e)
                return
            }
            MjpegMediaCodecPlayer.handleLog("VideoCSaocket.isConnected:${mVideoCSaocket?.isConnected}")
            //Thread.sleep(1000)
            if (mVideoCSaocket?.isConnected == true) {
                firstFrameComing = false
                mjpegMediaCodecPlayer = MjpegMediaCodecPlayer(mVideoCSaocket!!)
                mjpegMediaCodecPlayer.sourceDataPath = ivPic.context.filesDir.absolutePath + File.separator + "Download" + File.separator + "source_" + System.currentTimeMillis() + ".data"
                mjpegMediaCodecPlayer.videoFilePath = ivPic.context.filesDir.absolutePath + File.separator + "Download" + File.separator + "video_" + System.currentTimeMillis() + ".mp4"
                mjpegMediaCodecPlayer.logPath =
                    ivPic.context.filesDir.absolutePath + File.separator + "Download" + File.separator + "log_" + SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date()) + ".txt"
                var prePicGetTime = 0L
                mjpegMediaCodecPlayer.startPlayback(object : MjpegMediaCodecPlayer.OnGetPicDataListener {
                    override fun onGetPicData(picPackage: MjpegMediaCodecPlayer.PicPackage) {
                        synchronized(this) {
                            if (!firstFrameComing) {
                                firstFrameComing = true
                                MjpegMediaCodecPlayer.handleLog("收到第一帧图片")
                                onSuccess()
                            }
                        }
                        ivPic.post {
                            try {
                                if (TestConfig.showPicFrameIntervalTips) {
                                    if (prePicGetTime == 0L) {
                                        prePicGetTime = System.currentTimeMillis()
                                    } else {
                                        val cTime = System.currentTimeMillis()
                                        val interval = cTime - prePicGetTime
                                        MjpegMediaCodecPlayer.handleLog("图片帧间隔：${interval}ms")
                                        Toast.makeText(ivPic.context, "图片帧间隔：${interval}ms", Toast.LENGTH_SHORT).show()
                                        prePicGetTime = cTime
                                    }
                                }
                                val picData = picPackage.data
                                MjpegMediaCodecPlayer.handleLog("接收到图片帧,picPackage:$picPackage")
                                var bitmap = BitmapFactory.decodeByteArray(picData, 0, picData.size)

                                var rotationMatrix: Matrix? = null
                                /*Log.d("2222", "rotationDegree:$rotationDegree")
                                if (rotationDegree == 0f) {
                                    MjpegMediaCodecPlayer.handleLog("rotationDegree == 0f，不旋转")
                                }*/
                                if (rotationDegree in listOf(90f, 180f, 270f))  {
                                    rotationMatrix = Matrix().apply { postRotate(rotationDegree) }
                                } /*else {
                                        Log.d("2222", "旋转参数非法，只接受90，180， 270三种，当前参数：rotationDegree:$rotationDegree")
                                    }*/
                                //Log.d("2222", "rotationMatrix:$rotationMatrix")
                                if (rotationMatrix != null) {
                                    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, rotationMatrix, true)
                                }

                                ivPic.setImageBitmap(bitmap)
                                if (TestConfig.savePicFrame) {
                                    Thread {
                                        val fileWithPath = ivPic.context.filesDir.absolutePath + File.separator + "Download" + File.separator + "pic_" + picPackage.id + "_" + System.currentTimeMillis() + ".jpg"
                                        if (!File(fileWithPath).exists()) {
                                            if (!File(fileWithPath).parentFile.exists() && !File(fileWithPath).parentFile.mkdirs()) {
                                                return@Thread
                                            }
                                            if (!File(fileWithPath).createNewFile()) {
                                                return@Thread
                                            }
                                        }
                                        val fileOUtputStream = FileOutputStream(fileWithPath)
                                        try {
                                            fileOUtputStream.write(picData)
                                            fileOUtputStream.flush()
                                            fileOUtputStream.close()
                                        } catch (e: IOException) {
                                            e.printStackTrace()
                                            onFail?.let { it(e) }
                                        }
                                    }.start()
                                }
                            } catch (e: Exception) {
                                e.printStackTrace()
                                onFail?.let { it(e) }
                            }
                        }
                    }
                })
            } else {
                onFail?.let { it(Throwable("连接失败")) }
            }
        } catch (e: IOException) {
            e.printStackTrace()
            onFail?.let { it(e) }
        }
    }

    fun stopVideoPlay(pixelType: Int = 0): Boolean {
        //关闭摄像头
        val state = sendMsg(ObjectUtil.parseHexStringToBytes(when (pixelType) {
            0 -> {
                //1280*720
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 d4 000000 08000000 f6fd0000 0800 0005 d002 0000 0200"))
            }
            1 -> {
                //1024*720
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 07 000000 08000000 f6fd0000 0800 0004 d002 0000 0200"))
            }
            2 -> {
                //800*480
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 d9 000000 08000000 f6fd0000 0800 2003 e001 0000 0200"))
            }
            3 -> {
                //640*480
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 53 000000 08000000 f6fd0000 0800 8002 e001 0000 0200"))
            }
            4 -> {
                //480*320
                return sendMsg(ObjectUtil.parseHexStringToBytes("d5f0 0100 11111111 0100 1200 6a 000000 08000000 f6fd0000 0800 e001 4001 0000 0200"))
            }
            else -> ""
        }))
        /*if (this::mCameraSaocket.isInitialized && mCameraSaocket.isConnected) {
            mCameraSaocket.close()
        }*/
        destory()
        return state
    }

    fun startRecordVideo(context: Context): File {
        return mjpegMediaCodecPlayer.startRecordVideo(context)
    }

    fun configRotationDegree(degree: Float) {
        rotationDegree = degree
    }

    fun stopRecordVideo() {
        mjpegMediaCodecPlayer.stopRecordVideo()
    }

    fun destory() {
        mCameraSaocket?.close()
        mCameraSaocket = null
        mjpegMediaCodecPlayer.destory()
        mVideoCSaocket = null
    }

    private fun sendMsg(messageData: ByteArray): Boolean {
        val soc = mCameraSaocket ?: mVideoCSaocket
        try {
            if (soc?.isClosed != true && soc?.isOutputShutdown != true && soc?.isConnected == true) {
                val os = soc.getOutputStream()
                os.write(messageData) //写入完整数据包
                os.flush()
                Log.e(TAG, "发送成功:${ObjectUtil.bytes2Hex(messageData)}")
                return true
            } else {
                return false
            }
        } catch (e: IOException) {
            e.printStackTrace()
            return false
        }
    }
}